﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using MH.Lib.Data;

namespace MH.Lib.Serialization
{
    public class XmlSerializer
        : ISerializer
    {
        #region ISerializer

        /// <summary>
        /// Attempts to serialize data to given filename
        /// </summary>
        /// <param name="data"> Source data </param>
        /// <param name="filename"> Target filename </param>
        /// <returns> True if successful, false otherwise </returns>
        public bool Serialize(IPersonContainer data, string filename)
        {
            try
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;
                settings.IndentChars = "\t";

                // Create xml writer
                using (XmlWriter writer = XmlWriter.Create(filename, settings))
                {
                    writer.WriteStartDocument();
                    writer.WriteStartElement("Individuals");

                    foreach (var person in data)
                    {
                        // Serialize each person in container
                        writer.WriteStartElement("Individual");
                        writer.WriteAttributeString("id", person.ID);
                        writer.WriteAttributeString("first", person.FirstName);
                        writer.WriteAttributeString("last", person.LastName);
                        writer.WriteEndElement();
                    }

                    writer.WriteEndElement();
                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Attempts to deserialize data from given filename
        /// </summary>
        /// <param name="filename"> Source filename </param>
        /// <param name="data"> Target data </param>
        /// <returns> True if successful, false otherwise </returns>
        public bool Deserialize(string filename, out IPersonContainer data)
        {
            data = new PersonContainer();

            try
            {
                using (XmlReader reader = XmlReader.Create(filename))
                {
                    reader.MoveToContent();
                    while (reader.Read())
                    {
                        if (reader.NodeType != XmlNodeType.Element)
                            continue;

                        if (reader.Name != "Individual")
                            continue;

                        // Read element
                        XElement element = XNode.ReadFrom(reader) as XElement;
                        if (element == null)
                            continue;

                        // Read attributes
                        XAttribute id = element.Attribute("id");
                        XAttribute firstName = element.Attribute("first");
                        XAttribute lastName = element.Attribute("last");
                        if (id == null || firstName == null || lastName == null)
                            continue;

                        // Create new person
                        var person = new Person(id.Value, firstName.Value, lastName.Value);

                        // Insert to container
                        data.Insert(person);
                    }
                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        #endregion // ISerializer
    }
}
